﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.Revit;
using YJKArchMethodLibrary.Utils;
using YJKRamp.BarrierFreeRampKit;
using YJKRamp.Forms;
using YJKRevitCode.RevitDimensionUtility;
using TableTools;

namespace YJKRamp.RampDataManager
{
	public class RampManager
	{
		public RampManager(ExternalCommandData cmdData)
		{
			this.m_Revit = cmdData;
			this.m_UIDoc = cmdData.Application.ActiveUIDocument;
			this.m_doc = this.m_UIDoc.Document;
			this.GetInitializeInfo();
		}

		public List<string> LevelNames
		{
			get
			{
				List<string> list = new List<string>();
				foreach (ElementId elementId in this.m_LevelIds)
				{
					Element element = this.m_doc.GetElement(elementId);
					list.Add(element.Name);
				}
				return list;
			}
		}

		public List<double> LevelsElevation
		{
			get
			{
				List<double> list = new List<double>();
				foreach (ElementId elementId in this.m_LevelIds)
				{
					Element element = this.m_doc.GetElement(elementId);
					Level level = element as Level;
					list.Add(AssistFunc.feetToMM(level.Elevation) / 1000.0);
				}
				return list;
			}
		}

		public List<string> BoardStyleNames
		{
			get
			{
				List<string> list = new List<string>();
				foreach (ElementId elementId in this.m_BoradStyleIds)
				{
					Element element = this.m_doc.GetElement(elementId);
					list.Add(element.Name);
				}
				return list;
			}
		}

		public bool Create()
		{
			if (this.m_BoradStyleIds.Count < 1)
			{
				YJKMessageBox.Show("当前工程缺少厚度不小于100mm的“楼板样式”");
				return false;
			}
			List<Curve> list = this.SelectRefrenceCurves();
			if (list.Count == 0)
			{
				return false;
			}
			RampAnalyser rampAnalyser = new RampAnalyser(this.m_Revit);
			List<Curve> refCurvesList = new List<Curve>();
			string message = "";
			if (!rampAnalyser.SerializeCurves(list, ref refCurvesList, ref message))
			{
				YJKMessageBox.Show(message);
				return false;
			}
			return this.CreateFloorByRefCurves(refCurvesList);
		}

		public bool Edit()
		{
			List<Floor> ramps = this.GetRamps("选择一对成组坡道");
			if (ramps == null)
			{
				return false;
			}
			RampAnalyser rampAnalyser = new RampAnalyser(this.m_Revit);
			List<SegmentData> segmentDataList = null;
			Floor floor = null;
			Floor elem = null;
			bool flag = false;
			for (int i = 0; i < ramps.Count; i++)
			{
				Floor floor2 = ramps[i];
				for (int j = i + 1; j < ramps.Count; j++)
				{
					Floor floor3 = ramps[j];
					segmentDataList = new List<SegmentData>();
					string text = "";
					if (rampAnalyser.AnalyserRamp(floor2, floor3, ref segmentDataList, ref text))
					{
						floor = floor2;
						elem = floor3;
						flag = true;
						break;
					}
				}
			}
			if (!flag)
			{
				YJKMessageBox.Show("所选的坡道无法匹配！");
				return false;
			}
			CreateRampForm createRampForm = new CreateRampForm(this.m_Revit, this.BoardStyleNames, this.LevelNames, this.LevelsElevation, segmentDataList);
			createRampForm.SetFloorType(floor.FloorType.Name);
			createRampForm.Text = "编辑坡道";
			if (createRampForm.ShowDialog() != DialogResult.OK)
			{
				return false;
			}
			Transaction transaction = new Transaction(this.m_doc);
			transaction.Start("delete old ramps");
			this.m_doc.DeleteElement(floor);
			this.m_doc.DeleteElement(elem);
			transaction.Commit();
			RampCreater rampCreater = new RampCreater(this.m_Revit);
			FloorType floorType = this.m_doc.GetElement(this.m_BoradStyleIds[createRampForm.BoradStyleIndex]) as FloorType;
			return rampCreater.CreateFloorBySegementDataList(createRampForm.SegmentDataList, floorType);
		}

		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		public void DrawExpandedView()
		{
			List<Floor> ramps = this.GetRamps("选择一对成组坡道");
			if (ramps == null || ramps.Count < 2)
			{
				return;
			}
			RampAnalyser rampAnalyser = new RampAnalyser(this.m_Revit);
			Dictionary<Level, List<SegmentData>> dictionary = new Dictionary<Level, List<SegmentData>>();
			bool flag = false;
			for (int i = 0; i < ramps.Count; i++)
			{
				Floor floor = ramps[i];
				for (int j = i + 1; j < ramps.Count; j++)
				{
					Floor floor2 = ramps[j];
					string text = "";
					List<SegmentData> lstStandardSegData = new List<SegmentData>();
					if (rampAnalyser.AnalyserRamp(floor, floor2, ref lstStandardSegData, ref text))
					{
						rampAnalyser.GetAllSegmentData(this.m_doc, lstStandardSegData, dictionary);
						flag = true;
						break;
					}
				}
			}
			if (!flag || dictionary.Count < 1)
			{
				YJKMessageBox.Show("所选的坡道无法匹配！");
				return;
			}
			if (!this.ChangeView())
			{
				return;
			}
			DimensionType dimensionType = null;
			Transaction transaction = new Transaction(this.m_doc);
			transaction.Start("CreateDimType");
			try
			{
				dimensionType = RevitDimensionUtiltyMethod.GetDimensionType(this.m_doc, DimensionTypeEnum.AxisDimension, null);
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
				YJKMessageBox.Show("无法得到标注样式！");
				return;
			}
			if (dimensionType == null)
			{
				YJKMessageBox.Show("缺少标注样式！");
			}
			else
			{
				TextNoteType textNoteType = this.GetTextNoteType();
				if (textNoteType == null)
				{
					YJKMessageBox.Show("缺少文字样式！");
					return;
				}
				DrawExpandedViewForm drawExpandedViewForm = new DrawExpandedViewForm();
				if (drawExpandedViewForm.ShowDialog() != DialogResult.OK)
				{
					return;
				}
				XYZ ptOrigin = null;
				if (!this.SelelctPosision(ref ptOrigin))
				{
					return;
				}
				if (drawExpandedViewForm.Reversed)
				{
					foreach (KeyValuePair<Level, List<SegmentData>> keyValuePair in dictionary)
					{
						List<SegmentData> value = keyValuePair.Value;
						foreach (SegmentData segmentData in value)
						{
							segmentData.Reverse();
						}
						value.Reverse();
					}
				}
				int slopeType = this.GetSlopeType();
				DrawingKit drawingKit = new DrawingKit(this.m_Revit);
				FloorType floorType = ramps[0].FloorType;
				drawingKit.CreateExpandedView(dictionary, ptOrigin, dimensionType, textNoteType, floorType, slopeType, drawExpandedViewForm.DrawLeftDimension, drawExpandedViewForm.DrawTopDimension);
				return;
			}
		}

		private bool ChangeView()
		{
			return TableInterface.SwitchRampExpandedView(this.m_Revit) == null;
		}

		private bool SelelctPosision(ref XYZ pt)
		{
			try
			{
				XYZ xyz = this.m_Revit.Application.ActiveUIDocument.Selection.PickPoint("选择展开图的插入点");
				pt = new XYZ(xyz.X, xyz.Y, 0.0);
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private DimensionType GetDirmesionType(string strDimType)
		{
			DimensionType dimensionType = this.FindDimensionType(strDimType);
			if (dimensionType != null)
			{
				return dimensionType;
			}
			DimensionType dimensionType2 = this.FindDimensionType("HY-3.5-长仿宋-0.8(左下)");
			if (dimensionType2 == null)
			{
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc).OfClass(typeof(DimensionType));
				foreach (Element element in filteredElementCollector)
				{
					DimensionType dimensionType3 = (DimensionType)element;
					if (dimensionType3.StyleType == null)
					{
						dimensionType2 = dimensionType3;
						break;
					}
				}
			}
			if (dimensionType2 == null)
			{
				return null;
			}
			DimensionType dimensionType4 = null;
			Transaction transaction = new Transaction(this.m_doc);
			transaction.Start("CreateDimensionType");
			try
			{
				dimensionType4 = (dimensionType2.Duplicate(strDimType) as DimensionType);
				dimensionType4.get_Parameter(BuiltInParameter.DIM_STYLE_READ_CONVENTION).Set(3);
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
				return null;
			}
			return dimensionType4;
		}

		private DimensionType FindDimensionType(string strDimType)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc).OfClass(typeof(DimensionType));
			foreach (Element element in filteredElementCollector)
			{
				DimensionType dimensionType = (DimensionType)element;
				if (strDimType.CompareTo(dimensionType.Name.ToString()) == 0)
				{
					return dimensionType;
				}
			}
			return null;
		}

		private TextNoteType GetTextNoteType()
		{
			TextNoteType result = null;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc).OfClass(typeof(TextNoteType));
			foreach (Element element in filteredElementCollector)
			{
				TextNoteType textNoteType = element as TextNoteType;
				Parameter parameter = textNoteType.get_Parameter(BuiltInParameter.TEXT_SIZE);
				if (parameter != null && Geometry.IsEqual(parameter.AsDouble(), AssistFunc.mmToFeet(3.0), 0.001))
				{
					if (textNoteType.Name.IndexOf("仿宋") > -1)
					{
						return textNoteType;
					}
					result = textNoteType;
				}
			}
			return result;
		}

		private void GetInitializeInfo()
		{
			List<Level> sortLevels = Common.GetSortLevels(this.m_doc, double.MinValue, double.MaxValue);
			foreach (Level level in sortLevels)
			{
				if (level != null)
				{
					this.m_LevelIds.Add(level.Id);
				}
			}
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
			IList<Element> list = filteredElementCollector.WhereElementIsElementType().OfCategory(BuiltInCategory.OST_Floors).ToElements();
			foreach (Element element in list)
			{
				FloorType floorType = element as FloorType;
				if (floorType != null && !this.IsFloorTypeThickAlterable(floorType))
				{
					Parameter parameter = floorType.GetParameter(BuiltInParameter.FLOOR_ATTR_DEFAULT_THICKNESS_PARAM);
					if (parameter != null)
					{
						double val = parameter.AsDouble();
						if (Geometry.Greaterthan_Or_Equal(val, AssistFunc.mmToFeet(100.0)))
						{
							this.m_BoradStyleIds.Add(floorType.Id);
						}
					}
				}
			}
		}

		private List<Curve> SelectRefrenceCurves()
		{
			List<Curve> list = new List<Curve>();
			IList<Reference> list2 = null;
			Selection selection = this.m_Revit.Application.ActiveUIDocument.Selection;
			try
			{
				list2 = selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element, new RampDetailCurveFilter(), "选择连续模型/详图线");
			}
			catch (Exception)
			{
				return list;
			}
			if (list2.Count < 1)
			{
				return list;
			}
			foreach (Reference reference in list2)
			{
				Element element = this.m_doc.GetElement(reference);
				DetailLine detailLine = element as DetailLine;
				if (detailLine != null)
				{
					Line item = detailLine.GeometryCurve as Line;
					list.Add(item);
				}
				else
				{
					DetailArc detailArc = element as DetailArc;
					if (detailArc != null)
					{
						Arc item2 = detailArc.GeometryCurve as Arc;
						list.Add(item2);
					}
					else
					{
						ModelLine modelLine = element as ModelLine;
						if (modelLine != null)
						{
							Line item3 = modelLine.GeometryCurve as Line;
							list.Add(item3);
						}
						else
						{
							ModelArc modelArc = element as ModelArc;
							if (modelArc != null)
							{
								Arc item4 = modelArc.GeometryCurve as Arc;
								list.Add(item4);
							}
						}
					}
				}
			}
			return list;
		}

		private List<Floor> GetRamps(string statusPrompt)
		{
			List<Floor> list = new List<Floor>();
			List<Floor> result;
			try
			{
				IList<Reference> list2 = this.m_UIDoc.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element, statusPrompt);
				foreach (Reference reference in list2)
				{
					Element element = this.m_doc.GetElement(reference);
					Floor floor = element as Floor;
					if (floor != null)
					{
						list.Add(floor);
					}
				}
				result = list;
			}
			catch (Exception)
			{
				result = null;
			}
			return result;
		}

		private List<SegmentData> CurveList2SegmentDataList(List<Curve> refCurves, double bottomElevation, double topElevation)
		{
			double num = 0.0;
			foreach (Curve curve in refCurves)
			{
				num += curve.Length;
			}
			double dLeftWidth = 1000.0;
			double dRightWidth = 1000.0;
			CreateRampForm.ReadRampWidth(ref dLeftWidth, ref dRightWidth);
			double num2 = 0.0;
			List<SegmentData> list = new List<SegmentData>();
			foreach (Curve curve2 in refCurves)
			{
				double num3 = bottomElevation + num2 / num * (topElevation - bottomElevation);
				double dEndElevation = num3 + curve2.Length / num * (topElevation - bottomElevation);
				XYZ xyz = this.To2D(curve2.GetEndPoint(0));
				XYZ xyz2 = this.To2D(curve2.GetEndPoint(1));
				double dBulge = 0.0;
				if (curve2.GetType() == typeof(Arc))
				{
					Arc arc = curve2 as Arc;
					dBulge = Geometry.GetBulge(xyz, xyz2, arc.Center, arc.Normal.IsAlmostEqualTo(XYZ.BasisZ));
				}
				SegmentData item = new SegmentData(xyz, xyz2, dBulge, num3, dEndElevation, dLeftWidth, dRightWidth, 0.0);
				list.Add(item);
				num2 += curve2.Length;
			}
			return list;
		}

		private XYZ To2D(XYZ pt)
		{
			return new XYZ(pt.X, pt.Y, 0.0);
		}

		private bool CreateFloorByRefCurves(List<Curve> refCurvesList)
		{
			int currentLevelId = this.m_Revit.Application.ActiveUIDocument.ActiveView.GenLevel.Id.IntegerValue;
			List<double> levelsElevation = this.LevelsElevation;
			int num = this.m_LevelIds.FindIndex((ElementId s) => s.IntegerValue == currentLevelId);
			double num2;
			double topElevation;
			if (num == -1)
			{
				num2 = levelsElevation[0] * 1000.0;
				topElevation = levelsElevation[levelsElevation.Count - 1] * 1000.0;
			}
			else
			{
				num2 = levelsElevation[num] * 1000.0;
				if (num == levelsElevation.Count - 1)
				{
					topElevation = num2;
				}
				else
				{
					topElevation = levelsElevation[num + 1] * 1000.0;
				}
			}
			List<SegmentData> segmentDataList = this.CurveList2SegmentDataList(refCurvesList, num2, topElevation);
			CreateRampForm createRampForm = new CreateRampForm(this.m_Revit, this.BoardStyleNames, this.LevelNames, this.LevelsElevation, segmentDataList);
			if (createRampForm.ShowDialog() != DialogResult.OK)
			{
				return false;
			}
			RampCreater rampCreater = new RampCreater(this.m_Revit);
			FloorType floorType = this.m_doc.GetElement(this.m_BoradStyleIds[createRampForm.BoradStyleIndex]) as FloorType;
			return rampCreater.CreateFloorBySegementDataList(createRampForm.SegmentDataList, floorType);
		}

		private bool IsFloorTypeThickAlterable(FloorType fType)
		{
			CompoundStructure compoundStructure = fType.GetCompoundStructure();
			return compoundStructure.VariableLayerIndex >= 0;
		}

		private int GetSlopeType()
		{
			string path = Path.GetTempPath() + "CreateRampForm.dat";
			if (!File.Exists(path))
			{
				return 1;
			}
			FileStream fileStream = new FileStream(path, FileMode.Open);
			StreamReader streamReader = new StreamReader(fileStream);
			string value = string.Empty;
			string text = string.Empty;
			for (;;)
			{
				text = streamReader.ReadLine();
				if (text == null)
				{
					break;
				}
				value = text;
			}
			int result = 1;
			if (!string.IsNullOrEmpty(value))
			{
				try
				{
					bool flag = Convert.ToBoolean(value);
					if (flag)
					{
						result = 2;
					}
				}
				catch
				{
				}
			}
			streamReader.Close();
			fileStream.Close();
			return result;
		}

		private ExternalCommandData m_Revit;

		private UIDocument m_UIDoc;

		private Document m_doc;

		private List<ElementId> m_LevelIds = new List<ElementId>();

		private List<ElementId> m_BoradStyleIds = new List<ElementId>();
	}
}
